package com.wandian.texas;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.wandian.texas.dao.Impl.GameRoomDaoImpl;
import com.wandian.texas.db.DBMgr;
import com.wandian.texas.db.DaoManager;
import com.wandian.texas.entity.StandUpModel;
import com.wandian.texas.entity.UserInfoEntity;
import com.wandian.texas.protocol.Protocol;
import com.wandian.util.ArrayList;
import com.wandian.util.Log;
import com.wandian.xml.RoomConfigItem;

/**
 * @author long
 * @Create 2012-10-19 下午5:38:59
 * @QQ 108232706
 * @version 1.0
 * @description RoomMgr
 */
public class RoomMgr {

	/**
	 * 房间列表
	 */
	public static final ArrayList<RoomConfigItem> roomsList = new ArrayList<RoomConfigItem>();// 所有房间
	/**
	 * 房间哈希表
	 */
	public static final Map<Integer, RoomConfigItem> roomsMap = new ConcurrentHashMap<Integer, RoomConfigItem>();// 房间配置map
	//	public static final RoomConfigItem[]roomsMap = new ConcurrentHashMap<Integer, RoomConfigItem>();// 房间配置map
	/**
	 * 此份供房间使用，与GameRoom的seatUsers+UserSeatId类似,房间座位上玩家
	 */
	// public static final Map<Integer, ArrayList<SessionObject>> roomSeatMap =
	// new ConcurrentHashMap<Integer, ArrayList<SessionObject>>();// 房间座位上玩家map
	/**
	 * 房间所有玩家
	 */
	// public static final Map<Integer, ArrayList<SessionObject>> roomUserMap =
	// new ConcurrentHashMap<Integer, ArrayList<SessionObject>>();// 房间用户map
	private static boolean isInit = false;
	public static final byte bettime = 15;

	public static RoomConfigItem getRoom(int roomid) {
		return RoomMgr.roomsMap.get(roomid);
	}

	public static RoomConfigItem getRoom(UserInfoEntity user) {
		return getRoom(user.roomId);
	}

	public static RoomConfigItem getRoom(SessionObject session) {
		if (session.getUser() != null) {
			return getRoom(session.getUser().roomId);
		}
		return null;
	}

	/**
	 * 玩家进入房间
	 * 
	 * @param cmdObject
	 * @param roomid
	 */
	public static boolean inGame(SessionObject session, int roomid) {
		RoomConfigItem room = RoomMgr.roomsMap.get(roomid);
		if (room != null) {
			return room.inGame(session);
		}
		return false;
	}

	public static void loginOff(SessionObject session, int dbIndex, BaseCommandObject command) {
		UserInfoEntity user = session.getUser();
		int roomid = user.roomId;
		// int seatId = user.seatId;
		// user.state = -1;
		// BaseCommandObject
		// command=ThreadPool.getInstance().sessionMgrCommand();
		RoomConfigItem room = RoomMgr.getRoom(roomid);
		if (room != null) {
			RoomMgr.outGame(session, dbIndex, command);
			// 当前房间玩家都通知
			command.setCmd(Protocol.CMD_GAME_ROOM_SOCKET_CLOSE);
			// DataPacket dataPacket = new
			// DataPacket(Protocol.CMD_GAME_ROOM_SOCKET_CLOSE);
			// dataPacket.cmdId = Protocol.CMD_GAME_ROOM_SOCKET_CLOSE;
			command.writeBegin();
			command.writeByte((byte) 1);// 1标志位成功，0 失败
			command.writeInt(user.userId);
			command.writeEnd();
			UserMgr.I().broadCastToRoomUsers(roomid, command);
		}
	}

	public static RoomConfigItem getRoom(Integer roomid) {
		return RoomMgr.roomsMap.get(roomid);
	}

	public static int RoomSize() {
		return RoomMgr.roomsMap.size();
	}

	public static RoomConfigItem getRoomByIndex(int index) {
		return RoomMgr.roomsList.get(index);
	}

	/**
	 * 玩家进入房间
	 * 
	 * @param cmdObject
	 * @param roomid
	 */
	public static StandUpModel outGame(SessionObject session, int dbIndex, BaseCommandObject command) {
		RoomConfigItem room = RoomMgr.getRoom(session.RoomId());
		if (room == null)
			return null;
		room.gameRoom.InOutRoomLock.lock();
		try {
			// 退出房间之前检查数据
			UserInfoEntity user = session.getUser();
			//		int seatId = user.seatId;
			// Log.debug("退出房间之前");
			// Log.debug(String.format("房间所有人组gameUsers[%s]%s",
			// room.containsRoomUser(session) ? "包含" : "不包含", user.nickName));
			// Log.debug(String.format("房间9个坐位组userSeats[%s]%s",
			// room.contain9SeatUser(session) ? "包含" : "不包含", user.nickName));
			// Log.debug(String.format("房间坐位组userSeats[%s]%s",
			// room.containUserSeat(seatId) ? "包含" : "不包含", user.nickName));
			// Log.debug(String.format("房间等候组waitSeats[%s]%s",
			// room.containWaitSeat(seatId) ? "包含" : "不包含", user.nickName));
			// Log.debug(String.format("房间游戏数组gameUsers[%s]%s",
			// room.containGameUser(user) ? "包含" : "不包含", user.nickName));
			// 退出房间之后检查数据

			StandUpModel standUp = standupGame(session, dbIndex);
			if (standUp.isStandupSuc) {
				MoneyUpdateByStand(session.getUser(), room.id, standUp.seatId, dbIndex);
				broadcastStandUpCmd(room, standUp.seatId, session.getUser().money, command);
				broadcastRoomSeatChange(room, command);

			}
			room.RoomDoorLock().lock();
			try {
				if (room.containsRoomUser(session)) {
					standUp.isOutRoomSuc = true;
					broadcastOutGameRoom(session, room, command);
					room.removeRoomUser(session);
					//			Log.debug(String.format("[RoomMgr]玩家%s退出,从房间%s %s列表组删除,当前房间人数%s", session.NickName(), room.id, room.roomCode, room.roomUserSize()));
				} else {
					Log.error("房间内没有玩家:" + user.nickName);
				}
			} finally {
				room.RoomDoorLock().unlock();
			}
			// 如果玩家不是被游戏结束T出来的
			//		Log.debug(String.format("[[处理游戏房间数据]]!standUp.isPlaying:%s,standUp.curSeatId:%s,standUp.gameSeatCount:%s,standUp.isGameOver:%s,standUp.isCurUser:%s,,standUp.isMaxRaiser:%s", standUp.isPlaying, standUp.curSeatId, standUp.gameSeatCount, standUp.isGameOver, standUp.isCurUser, standUp.isMaxRaiser));
			broadcastStandUpGameOver(room, session, standUp.isPlaying, standUp.isGameOver, standUp.isCurUser, standUp.isMaxRaiser, command);
			session.getUser().roomId = 0;

			if (standUp.isRoomChange) {
				broadcastRoomChange(room, command);
			}
			// 退出房间之后检查数据
			// Log.debug("退出房间之后");
			// Log.debug(String.format("房间所有人组gameUsers[%s]%s",
			// room.containsRoomUser(session) ? "包含" : "不包含", user.nickName));
			// Log.debug(String.format("房间9个坐位组userSeats[%s]%s",
			// room.contain9SeatUser(session) ? "包含" : "不包含", user.nickName));
			// Log.debug(String.format("房间坐位组userSeats[%s]%s",
			// room.containUserSeat(seatId) ? "包含" : "不包含", user.nickName));
			// Log.debug(String.format("房间等候组waitSeats[%s]%s",
			// room.containWaitSeat(seatId) ? "包含" : "不包含", user.nickName));
			// Log.debug(String.format("房间游戏数组gameUsers[%s]%s",
			// room.containGameUser(user) ? "包含" : "不包含", user.nickName));
			return standUp;
		} finally {
			room.gameRoom.InOutRoomLock.unlock();
		}
	}

	private static void broadcastOutGameRoom(SessionObject session, RoomConfigItem room, BaseCommandObject command) {
		// 当前房间玩家都通知
		// DataPacket dataPacket = new DataPacket(Protocol.OutGameRoomCmd);
		command.setCmd(Protocol.OutGameRoomCmd);
		command.writeBegin();
		command.writeByte((byte) 1);// 1标志位成功，0 失败
		command.writeInt(session.getUser().userId);
		command.writeEnd();
		UserMgr.I().broadCastToRoomUsers(room, command);
	}

	/**
	 * 坐下
	 * 
	 * @param cmdObject
	 * @param roomid
	 */
	public static boolean sitdownGame(SessionObject session, int roomid, int seatId, float stake, int dbIndex, BaseCommandObject command) {
		// ArrayList<SessionObject> roomSeatList =
		// RoomMgr.roomSeatMap.get(roomid);
		RoomConfigItem room = roomsMap.get(roomid);
		if (room == null)
			return false;
		UserInfoEntity user = session.getUser();
		// 从AccountDB PlayerInfo 取玩家的钱，保证是最新的，stake:money=1:1
		user.money = DaoManager.GameRoomDao(dbIndex).getUserMoney(user.AccountId);
		if (user.money < room.minTake) {
			return false;
		}
		if (stake < room.minTake || stake > room.maxTake) {
			return false;
		}

		//				Log.debug(String.format("[RoomMgr]玩家身上的钱合法,money:%s,minTake:%s,maxTake:%s", user.money, room.minTake, room.maxTake));
		//					Log.debug(String.format("[RoomMgr]玩家下注筹码合法,stake:%s,money:%s,minTake:%s,maxTake:%s", stake, user.money, room.minTake, room.maxTake));
		room.GameSeatLock().lock();
		try {
			if (room.sitDown(session, seatId)) {
				user.isNew = true;
				user.seatId = seatId;
				user.stake = stake;
				user.state = GameData.WAIT_NEXT_GAME;
				float subMoney = stake / GameData.StakeToMoney;
				user.money -= stake;
				// 调用存储过程subMoney SubPlayerMoney
				if (DaoManager.GameRoomDao(dbIndex).executeProcedureReturn("SubPlayerMoney", DBMgr.AccountDB, user.AccountId, subMoney) != 1) {
//					throw new IllegalArgumentException("db error");
					// 失败~
					room.standUp(session, seatId);
					if (user.stake > 0) {
						float addMoney = user.stake / GameData.StakeToMoney;
						//			user.money += addMoney;
						// 调用存储过程 [AddPlayerMoney]
						if (GamePool.gameRoomDao(dbIndex).executeNoQuery("AddPlayerMoney", DBMgr.AccountDB, user.AccountId, addMoney) == 1) {
							// 影响行为1，才成功~失败~
							user.money += user.stake;
							user.stake = 0;
							//				user.money -= addMoney;
						} else {
							throw new IllegalArgumentException("[MoneyUpdateByStand] AddPlayerMoney error,not effect one line");
						}
					}
					return false;
				}
				// 身上钱发生变化，存入兑换表
				if (!DaoManager.GameRoomDao(dbIndex).addSitStandLog(roomid, 0, user.seatId, user, 0, user.userName + "坐下筹码+" + user.stake)) {
//					throw new IllegalArgumentException("db error");
					Log.error("[RoomMgr]玩家登陆,保存状态失败!");
					room.standUp(session, seatId);
					if (user.stake > 0) {
						float addMoney = user.stake / GameData.StakeToMoney;
						//			user.money += addMoney;
						// 调用存储过程 [AddPlayerMoney]
						if (GamePool.gameRoomDao(dbIndex).executeNoQuery("AddPlayerMoney", DBMgr.AccountDB, user.AccountId, addMoney) == 1) {
							// 影响行为1，才成功~失败~
							user.money += user.stake;
							user.stake = 0;
							//				user.money -= addMoney;
						} else {
							throw new IllegalArgumentException("[MoneyUpdateByStand] AddPlayerMoney error,not effect one line");
						}
					}
					return false;
				}
				room.canSetRoom.set(false);
				// 广播人数变化
				broadcastRoomSeatChange(room, command);
				return true;
			} else {
				return false;
			}
		} finally {
			room.GameSeatLock().unlock();
		}
		//Log.debug(String.format("[RoomMgr]玩家操作不合法，玩家已经在坐位上,money:%s,minTake:%s,maxTake:%s", user.money, room.minTake, room.maxTake));
		//Log.debug(String.format("[RoomMgr]玩家下注筹码不合法,stake:%s,money:%s,minTake:%s,maxTake:%s", stake, user.money, room.minTake, room.maxTake));

	}

	/**
	 * 站起，未离开
	 * 
	 * @param cmdObject
	 * @param roomid
	 */
	public static void sendStandup(SessionObject session, int dbIndex, BaseCommandObject command, boolean kick) {
		UserInfoEntity user = session.getUser();
		int seatId = user.seatId;
		//		user.money = 11;
		//		float money = user.money + user.stake;
		StandUpModel standUp = standupGame(session, dbIndex);
		RoomConfigItem room = RoomMgr.getRoom(user.roomId);
		if (standUp.isStandupSuc) {
			if (seatId == room.maxStakeSeat() && !standUp.isGameOver) {
				room.setMaxStake();
			}
			MoneyUpdateByStand(session.getUser(), room.id, standUp.seatId, dbIndex);
			broadcastStandUpCmd(room, seatId, user.money, command);
		}
		if (standUp.isRoomChange) {
			broadcastRoomChange(room, command);
		}
		if (!kick) {
			Log.debug(String.format("[[处理游戏房间数据]]standUp.isPlaying:%s,standUp.curSeatId:%s,standUp.gameSeatCount:%s,standUp.isGameOver:%s,standUp.isCurUser:%s,,standUp.isMaxRaiser:%s", standUp.isPlaying, standUp.curSeatId, standUp.gameSeatCount, standUp.isGameOver, standUp.isCurUser, standUp.isMaxRaiser));
			broadcastStandUpGameOver(room, session, standUp.isPlaying, standUp.isGameOver, standUp.isCurUser, standUp.isMaxRaiser, command);

		}
	}

	/**
	 * 站起，未离开
	 * 
	 * @param cmdObject
	 * @param roomid
	 */
	private static StandUpModel standupGame(SessionObject session, int dbIndex) {

		StandUpModel standUp = new StandUpModel();
		UserInfoEntity user = session.getUser();
		if (user.seatId <= 0) {
			return standUp;
		}
		standUp.seatId = user.seatId;
		//		Log.debug("玩家" + user.nickName + "准备站起,坐位" + user.seatId);
		RoomConfigItem room = roomsMap.get(user.roomId);
		/*
				Log.debug("站起来之前");
				Log.debug(String.format("房间所有人组gameUsers[%s]%s", room.containsRoomUser(session) ? "包含" : "不包含", user.nickName));
				Log.debug(String.format("房间9个坐位组userSeats[%s]%s", room.contain9SeatUser(session) ? "包含" : "不包含", user.nickName));
				Log.debug(String.format("房间坐位组userSeats[%s]%s", room.containUserSeat(standUp.seatId) ? "包含" : "不包含", user.nickName));
				Log.debug(String.format("房间等候组waitSeats[%s]%s", room.containWaitSeat(standUp.seatId) ? "包含" : "不包含", user.nickName));
				Log.debug(String.format("房间游戏数组gameUsers[%s]%s", room.containGameUser(user) ? "包含" : "不包含", user.nickName));
		*/
		if (room != null) {
			room.GameSeatLock().lock();
			try {
				// --房间游戏结束，需要先保存最终坐位信息-->
				if (room.isPlaying()) {
					// 从gameUsers删除
					room.standUp(dbIndex, session);
					standUp.isCurUser = room.curSeatId() == user.seatId;
					standUp.isMaxRaiser = room.maxRaiseSeatId() == user.seatId;
					standUp.curSeatId = room.curSeatId();
					if (!room.doingGameOver()) {
						standUp.isGameOver = room.isGameOver();
					} else {
						standUp.isGameOver = false;
					}
					// 最后一个离开坐位的赢
					//				if (room.gameUsersSize() == 0 && !room.doingGameOver()) {
					//					room.gameRoom.gameOverUsers.add(user);
					//					user.gameOverSeatId = user.seatId;
					//					room.gameRoom.lastLeaveGameOver = true;
					//				}
					standUp.isPlaying = true;
				}
				standUp.gameSeatCount = room.gameUsersSize();
				standUp.seatIndex = user.seatId;
				// seatUsers .UserSeat WaitSeat
				if (room.standUp(session, user.seatId)) {

					standUp.isStandupSuc = true;
					standUp.isRoomChange = true;
					if (room.roomSeatSize() < 2) {
						room.gameRoom.isNewGame = true;
					}
					if (room.roomSeatSize() <= 0) {
						room.canSetRoom.set(true);
						room.seat = GameData.ROOMSEAT;
						room.minBlind = GameData.ROOMMINBLIND;
						room.maxBlind = GameData.ROOMMAXBLIND;
						room.minTake = GameData.ROOMMINTAKE;
						room.maxTake = GameData.ROOMMAXTAKE;
						// room.isPlaying(false);
						//					Log.debug(String.format("[RoomMgr]房间%s内座位上人数为0,房间信息重新设置为默认,", room.id, room.getName()));
					}
					user.seatId = 0;
					//				Log.debug(String.format("[RoomMgr]玩家%s起立,", user.nickName));
				}
			} finally {
				room.GameSeatLock().unlock();
			}
		}
		/*
				Log.debug("站起来之后");
				Log.debug(String.format("房间所有人组gameUsers[%s]%s", room.containsRoomUser(session) ? "包含" : "不包含", user.nickName));
				Log.debug(String.format("房间9个坐位组userSeats[%s]%s", room.contain9SeatUser(session) ? "包含" : "不包含", user.nickName));
				Log.debug(String.format("房间坐位组userSeats[%s]%s", room.containUserSeat(standUp.seatId) ? "包含" : "不包含", user.nickName));
				Log.debug(String.format("房间等候组waitSeats[%s]%s", room.containWaitSeat(standUp.seatId) ? "包含" : "不包含", user.nickName));
				Log.debug(String.format("房间游戏数组gameUsers[%s]%s", room.containGameUser(user) ? "包含" : "不包含", user.nickName));*/
		return standUp;
	}

	private static void MoneyUpdateByStand(UserInfoEntity user, int roomId, int seatId, int dbIndex) {
		// 身上钱发生变化，存入兑换表
		float stake = user.stake;
		// user.state = 11;
		// 身上钱发生变化，存入兑换表
		GameRoomDaoImpl gameDao = GamePool.gameRoomDao(dbIndex);
		if (stake > 0) {
			float addMoney = user.stake / GameData.StakeToMoney;
			//			user.money += addMoney;
			// 调用存储过程 [AddPlayerMoney]
			if (gameDao.executeNoQuery("AddPlayerMoney", DBMgr.AccountDB, user.AccountId, addMoney) == 1) {
				// 影响行为1，才成功~失败~
				user.stake = 0;
				//				user.money -= addMoney;
			} else {
				throw new IllegalArgumentException("[MoneyUpdateByStand] AddPlayerMoney error,not effect one line");
			}
		}
		user.money = gameDao.getUserMoney(user.AccountId);
		// --可能游戏没有结束，玩家站起来了，所以在gameuser里没有他，那么就无法通过sp_AddPlayMoneyLog清除GameBet,在这里清除
		if (!gameDao.addSitStandLog(roomId, 0, seatId, user, 0, user.userName+"站起筹码-" + stake)) {
			Log.error("[RoomMgr]站起筹码-保存状态失败!");
		}

	}

	private static void broadcastStandUpGameOver(RoomConfigItem room, SessionObject session, boolean isPlaying, boolean isGameOver, boolean isCurUser, boolean isMaxRaiser, BaseCommandObject command) {
		// 如果游戏在进行的时候，有人站起，剩余人数为1时，游戏自动结束，并计算奖池
		if (isPlaying) {
			if (isGameOver && !room.doingGameOver()) {
				// Game Over
				room.cancel();
				// room.isPlaying(false);
				room.curSeatId(0);
				// GamePool.GameOverByLeftOneOrAllIn(room, new
				// BaseCommandObject(session, new DataPacket()),
				// room.boolShowCard());
				GamePool.GameOverByLeftOneOrAllIn(room, command, room.boolShowCard());
				// GamePool.GameOverAndStartNew(room, new BaseCommandObject(
				// session, new DataPacket()), false);
			} else {
				if (isMaxRaiser && !room.doingGameOver()) {
					if (room.resetStandMaxRaiser() == 0 && !room.doingGameOver()) {
						room.cancel();
						// room.isPlaying(false);
						room.curSeatId(0);
						// GamePool.GameOverByLeftOneOrAllIn(room, new
						// BaseCommandObject(session, new DataPacket()),
						// room.boolShowCard());
						GamePool.GameOverByLeftOneOrAllIn(room, command, room.boolShowCard());
					}
				}
				if (isCurUser && !room.doingGameOver()) {
					room.cancel();
					// room.nextSeat();
					// GamePool.operationNext(room, new BaseCommandObject(new
					// DataPacket(), session.getUser()));
					GamePool.operationNext(room, command);
				}
			}

		}
	}

	private static void broadcastStandUpCmd(RoomConfigItem room, int seatId, float money, BaseCommandObject command) {
		// 广播站起
		// 先广播站起，移除界面显示
		command.setCmd(Protocol.StandUpCmd);
		command.writeBegin();
		command.writeInt(seatId);
		command.writeFloat(money);
		command.writeInt(0);
		command.writeEnd();
		UserMgr.I().broadCastToRoomUsers(room, command);
	}

	private static void broadcastRoomChange(RoomConfigItem room, BaseCommandObject command) {
		// DataPacket dataPacket = new DataPacket(Protocol.CMD_ROOMINFOUPDATE);
		command.setCmd(Protocol.CMD_ROOMINFOUPDATE);
		command.writeBegin();
		command.writeByte((byte) 0);
		command.writeInt(room.id);
		command.writeString(room.getName());
		command.writeInt(room.seat);
		command.writeFloat(room.minBlind);
		command.writeFloat(room.maxBlind);
		command.writeFloat(room.minTake);
		command.writeFloat(room.maxTake);
		command.writeInt(room.roomSeatSize());
		command.writeEnd();
		UserMgr.I().broadCastToAllOnlines(command);
	}

	private static void broadcastRoomSeatChange(RoomConfigItem room, BaseCommandObject command) {
		// DataPacket dataPacket = new
		// DataPacket(Protocol.CMD_ROOMPLAYERNUMCHANGE);
		command.setCmd(Protocol.CMD_ROOMPLAYERNUMCHANGE);
		command.writeBegin();
		command.writeInt(room.id);
		command.writeInt(room.roomSeatSize());
		command.writeEnd();
		UserMgr.I().broadCastToAllOnlines(command);
	}

	public static int getFastEnterRoom() {
		int roomid = -1;
		RoomConfigItem room;
		int leftSeat = 10;
		int tempLeftSeat;
		for (int i = 0; i < roomsList.size(); i++) {
			room = roomsList.get(i);
			tempLeftSeat = room.seat - room.roomGameSeatSize();
			if (tempLeftSeat > 0 && tempLeftSeat < leftSeat) {
				roomid = room.id;
				leftSeat = tempLeftSeat;
			}
		}
		return roomid;
	}

	public static boolean init() {
		if (isInit)
			return true;
		isInit = true;
		if (GameData.SERVER.RoomCount <= 0) {
			Log.error("房间数必须大于0");
			return false;
		}
		int roomCount = GameData.SERVER.RoomCount;
		int floorCount = GameData.getInt("RoomCountPerFloor");// roomCount/5;
		if (GameData.getFloat("RoomCountPerFloor") == 1) {

			int roomCode;
			int num;
			for (int i = 1; i <= roomCount; i++) {
				num = (((i - 1) / floorCount) + 1);
				roomCode = num * 100 + (i - floorCount * (num - 1));
				RoomConfigItem room = new RoomConfigItem(i, roomCode);
				roomsList.add(room);
				roomsMap.put(i, room);
				// roomSeatMap.put(i, new ArrayList<SessionObject>());
			}
		} else {
			for (int i = 1; i <= roomCount; i++) {
				RoomConfigItem room = new RoomConfigItem(i, i);
				roomsList.add(room);
				roomsMap.put(i, room);
				// roomSeatMap.put(i, new ArrayList<SessionObject>());
			}
		}

		return true;
	}
}
